home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 2: Applications / Linux Cubed Series 2 - Applications.iso / circuits / irsim-ca.2 / irsim-ca / irsim-cap-9.2 / src / irsim / network.c < prev    next >
C/C++ Source or Header  |  1994-07-20  |  12KB  |  552 lines

  1. /* 
  2.  *     ********************************************************************* 
  3.  *     * Copyright (C) 1988, 1990 Stanford University.                     * 
  4.  *     * Permission to use, copy, modify, and distribute this              * 
  5.  *     * software and its documentation for any purpose and without        * 
  6.  *     * fee is hereby granted, provided that the above copyright          * 
  7.  *     * notice appear in all copies.  Stanford University                 * 
  8.  *     * makes no representations about the suitability of this            * 
  9.  *     * software for any purpose.  It is provided "as is" without         * 
  10.  *     * express or implied warranty.  Export of this software outside     * 
  11.  *     * of the United States of America may require an export license.    * 
  12.  *     ********************************************************************* 
  13.  */
  14.  
  15. #include <stdio.h>
  16. #include "defs.h"
  17. #include "net.h"
  18. #include "globals.h"
  19.  
  20. /* event driven mosfet simulator. Chris Terman (2/80) */
  21.  
  22. public    iptr  hinputs = NULL;    /* list of nodes to be driven high */
  23. public    iptr  linputs = NULL;    /* list of nodes to be driven low */
  24. public    iptr  uinputs = NULL;    /* list of nodes to be driven X */
  25. public    iptr  xinputs = NULL;    /* list of nodes to be removed from input */
  26.  
  27. public    iptr  infree = NULL;    /* unused input list cells */
  28.  
  29. public    iptr  *listTbl[8];
  30.  
  31. public
  32. #define    FreeInput( X )    (X)->next = infree, infree = (X)
  33.  
  34.  
  35. public void init_listTbl()
  36.   {
  37.     int  i;
  38.  
  39.     for( i = 0; i < 8; listTbl[ i++ ] = NULL );
  40.     listTbl[ INPUT_NUM( H_INPUT ) ] = &hinputs;
  41.     listTbl[ INPUT_NUM( L_INPUT ) ] = &linputs;
  42.     listTbl[ INPUT_NUM( U_INPUT ) ] = &uinputs;
  43.     listTbl[ INPUT_NUM( X_INPUT ) ] = &xinputs;
  44.   }
  45.  
  46.  
  47. #define    pvalue( node_name, node )    \
  48.     lprintf( stdout, "%s=%c ", (node_name), "0XX1"[(node)->npot] )
  49.  
  50.  
  51. private void pgvalue( t )
  52.   register tptr  t;
  53.   {
  54.     register nptr  n;
  55.     static char    *states[] = { "OFF", "ON", "UKNOWN", "WEAK" };
  56.  
  57.     if( debug )
  58.     lprintf( stdout, "[%s] ", states[t->state] );
  59.  
  60.     if( t->ttype & GATELIST )
  61.       {
  62.     lprintf( stdout, "( " );
  63.     for( t = (tptr) t->gate; t != NULL; t = t->scache.t )
  64.       {
  65.         n = t->gate;
  66.         pvalue( pnode( n ), n );
  67.       }
  68.  
  69.     lprintf( stdout, ") " );
  70.       }
  71.     else
  72.       {
  73.     n = t->gate;
  74.     pvalue( pnode( n ), n );
  75.       }
  76.   }
  77.  
  78.  
  79. private void pr_one_res( s, r )
  80.   char     *s;
  81.   double  r;
  82.   {
  83.     if( r < 1e-9 or r > 100e9 )
  84.         (void) sprintf( s, "%2.1e", r );
  85.     else
  86.       {
  87.     int  e = 3;
  88.  
  89.     if( r >= 1000.0 )
  90.         do { e++; r *= 0.001; } while( r >= 1000.0 );
  91.     else if( r < 1 and r > 0 )
  92.         do { e--; r *= 1000; } while( r < 1.0 );
  93.     (void) sprintf( s, "%.1f%c", r, "num\0KMG"[ e ] );
  94.       }
  95.   }
  96.  
  97.  
  98. private void pr_t_res( fp, r )
  99.   FILE     *fp;
  100.   Resists  *r;
  101.   {
  102.     char    buf[3][15];
  103.  
  104.     pr_one_res( buf[0], r->rstatic );
  105.     pr_one_res( buf[1], r->dynhigh );
  106.     pr_one_res( buf[2], r->dynlow );
  107.     lprintf( fp, "[%s, %s, %s]", buf[0], buf[1], buf[2] );
  108.   }
  109.  
  110.  
  111. private void ptrans( t )
  112.   register tptr  t;
  113.   {
  114.     lprintf( stdout, "%s ", ttype[ BASETYPE( t->ttype ) ] );
  115.     if( BASETYPE( t->ttype ) != RESIST )
  116.     pgvalue( t );
  117.  
  118.     pvalue( pnode( t->source ), t->source );
  119.     pvalue( pnode( t->drain ), t->drain );
  120.     pr_t_res( stdout, t->r );
  121.     if( t->tlink != t and (treport & REPORT_TCOORD) )
  122.     lprintf( stdout, " <%d,%d>\n", t->x.pos, t->y.pos );
  123.     else
  124.     lprintf( stdout, "\n" );
  125.   }
  126.  
  127.  
  128. public void idelete( n, list )
  129.   register nptr  n;
  130.   register iptr  *list;
  131.   {
  132.     register iptr  p = *list;
  133.     register iptr  q;
  134.  
  135.     if( p == NULL )
  136.     return;
  137.     else if( p->inode == n )
  138.       {
  139.     *list = p->next;
  140.     FreeInput( p );
  141.       }
  142.     else
  143.       {
  144.     for( q = p->next; q != NULL; p = q, q = p->next )
  145.         if( q->inode == n )
  146.           {
  147.         p->next = q->next;
  148.         FreeInput( q );
  149.         return;
  150.           }
  151.       }
  152.   }
  153.  
  154.  
  155. public void iinsert( n, list )
  156.   nptr  n;
  157.   iptr  *list;
  158.   {
  159.     register iptr  p = infree;
  160.  
  161.     if( p == NULL )
  162.     p = infree = (iptr) MallocList( sizeof( struct Input ), 1 );
  163.     infree = p->next;
  164.  
  165.     p->next = *list;
  166.     *list = p;
  167.     p->inode = n;
  168.   }
  169.  
  170.  
  171. public void iinsert_once( n, list )
  172.   nptr  n;
  173.   iptr  *list;
  174.   {
  175.     register iptr  p;
  176.  
  177.     for( p = *list; p != NULL; p = p->next )
  178.     if( p->inode == n )
  179.         return;
  180.  
  181.     iinsert( n, list );
  182.   }
  183.  
  184.  
  185. private    int clear_input( n )
  186.   register nptr  n;
  187.   {
  188.     if( not( n->nflags & POWER_RAIL ) )
  189.     n->nflags &= ~INPUT;
  190.     return( 0 );
  191.   }
  192.  
  193.  
  194. public void ClearInputs()
  195.   {
  196.     register int   i;
  197.     register iptr  p, next;
  198.     register nptr  n;
  199.  
  200.     for( i = 0; i < 5; i++ )
  201.       {
  202.     if( listTbl[ i ] == NULL )
  203.         continue;
  204.     for( p = *listTbl[ i ]; p != NULL; p = next )
  205.       {
  206.         next = p->next;
  207.         n = p->inode;
  208.         FreeInput( p );
  209.         if( not( n->nflags & POWER_RAIL ) )
  210.         n->nflags &= ~(INPUT_MASK | INPUT);
  211.       }
  212.     *(listTbl[ i ]) = NULL;
  213.       }
  214.     walk_net( clear_input, (char *) 0 );
  215.   }
  216.  
  217.  
  218. /*
  219.  * set/clear input status of node and add/remove it to/from corresponding list.
  220.  */
  221. public int setin( n, which )
  222.   register nptr  n;
  223.   char           *which;
  224.   {
  225.     while( n->nflags & ALIAS )
  226.     n = n->nlink;
  227.  
  228.     if( n->nflags & (POWER_RAIL | MERGED) )    /* Gnd, Vdd, or merged node */
  229.       {
  230.     if( (n->nflags & MERGED) or "lxuh"[ n->npot ] != *which )
  231.         lprintf( stdout, "Can't drive `%s' to `%c'\n",
  232.          pnode( n ), *which );
  233.       }
  234.     else
  235.       {
  236.     iptr  *list = listTbl[ INPUT_NUM( n->nflags ) ];
  237.  
  238. #    define    WASINP( N, P )    ( ((N)->nflags & INPUT) && (N)->npot == (P) )
  239.  
  240.     switch( *which )
  241.       {
  242.         case 'h' :
  243.         if( list != NULL and list != &hinputs )
  244.           {
  245.             n->nflags = n->nflags & ~INPUT_MASK;
  246.             idelete( n, list );
  247.           }
  248.         if( not (list == &hinputs or WASINP( n, HIGH )) )
  249.           {
  250.             n->nflags = (n->nflags & ~INPUT_MASK) | H_INPUT;
  251.             iinsert( n, &hinputs );
  252.           }
  253.         break;
  254.  
  255.         case 'l' :
  256.         if( list != NULL and list != &linputs )
  257.           {
  258.             n->nflags = n->nflags & ~INPUT_MASK;
  259.             idelete( n, list );
  260.           }
  261.         if( not (list == &linputs or WASINP( n, LOW )) )
  262.           {
  263.             n->nflags = (n->nflags & ~INPUT_MASK) | L_INPUT;
  264.             iinsert( n, &linputs );
  265.           }
  266.         break;
  267.  
  268.         case 'u' :
  269.         if( list != NULL and list != &uinputs )
  270.           {
  271.             n->nflags = n->nflags & ~INPUT_MASK;
  272.             idelete( n, list );
  273.           }
  274.         if( not (list == &uinputs or WASINP( n, X )) )
  275.           {
  276.             n->nflags = (n->nflags & ~INPUT_MASK) | U_INPUT;
  277.             iinsert( n, &uinputs );
  278.           }
  279.         break;
  280.  
  281.         case 'x' :
  282.         if( list == &xinputs )
  283.             break;
  284.         if( list )
  285.           {
  286.             n->nflags = n->nflags & ~INPUT_MASK;
  287.             idelete( n, list );
  288.           }
  289.         if( n->nflags & INPUT )
  290.           {
  291.             n->nflags = (n->nflags & ~INPUT_MASK) | X_INPUT;
  292.             iinsert( n, &xinputs );
  293.           }
  294.         break;
  295.         default :
  296.         return( 0 );
  297.       }
  298.       }
  299.     return( 1 );
  300.   }
  301.  
  302.  
  303. private int wr_value( n, fp )
  304.   register nptr  n;
  305.   FILE           *fp;
  306.   {
  307.     if( not (n->nflags & (ALIAS | POWER_RAIL)) )
  308.       {
  309.     int ch = ((n->nflags & INPUT) ? '4' : '0') + n->npot;
  310.     (void) putc( ch, fp );
  311.       }
  312.     return( 0 );
  313.   }
  314.  
  315.  
  316. public int wr_state( fname )
  317.   char  *fname;
  318.   {
  319.     FILE  *fp;
  320.  
  321.     if( (fp = fopen( fname, "w" )) == NULL )
  322.     return( 1 );
  323.  
  324.     (void) fprintf( fp, "%d\n", nnodes );
  325.     walk_net( wr_value, (char *) fp );
  326.     (void) fclose( fp );
  327.     return( 0 );
  328.   }
  329.  
  330.  
  331. typedef struct
  332.   {
  333.     FILE  *file;
  334.     int   errs;
  335.     int   restore;
  336.   } StateFile;
  337.  
  338.  
  339. private int rd_stvalue( n, st )
  340.   register nptr  n;
  341.   StateFile      *st;
  342.   {
  343.     int   ch, inp;
  344.  
  345.     if( n->nflags & (ALIAS | POWER_RAIL) )
  346.     return( 0 );
  347.  
  348.     FreeHistList( n );
  349.     while( n->events != NULL )        /* remove any pending events */
  350.     free_event( n->events );
  351.  
  352.     if( st->file == NULL )
  353.       {
  354.     ch = X;
  355.     st->errs ++;
  356.       }
  357.     else
  358.       {
  359.     ch = getc( st->file );
  360.     if( ch == EOF )
  361.       {
  362.         ch = X;
  363.         st->errs ++;
  364.         (void) fclose( st->file );
  365.         st->file = NULL;
  366.       }
  367.     else if( ch < '0' or ch > '7' or ch == '2' or ch == '6' )
  368.       {
  369.         st->errs ++;
  370.         ch = X;
  371.       }
  372.     else if( st->restore and ch >= '4' )
  373.       {
  374.         ch = ch - '4';
  375.         inp = 1;
  376.       }
  377.     else
  378.       {
  379.         ch = (ch - '0') & (LOW | X | HIGH);
  380.         inp = 0;
  381.       }
  382.       }
  383.  
  384.     if( n->nflags & MERGED )
  385.     return( 0 );
  386.  
  387.     if( inp )
  388.     n->nflags |= INPUT;
  389.  
  390.     n->head.val = ch;
  391.     n->head.inp = inp;
  392.  
  393.     if( ch != n->npot )
  394.       {
  395.     register lptr  l;
  396.     register tptr  t;
  397.  
  398.     n->npot = ch;
  399.     for( l = n->ngate; l != NULL; l = l->next )
  400.       {
  401.         t = l->xtor;
  402.         t->state = compute_trans_state( t );
  403.       }
  404.       }
  405.     return( 0 );
  406.   }
  407.  
  408.  
  409. public char *rd_state( fname, restore )
  410.   char  *fname;
  411.   int   restore;
  412.   {
  413.     char       rline[25];
  414.     StateFile  st;
  415.  
  416.     if( (st.file = fopen( fname, "r" )) == NULL )
  417.     return( "can not read state file\n" );
  418.  
  419.     (void) fgetline( rline, 25, st.file );
  420.     if( atoi( rline ) != nnodes )
  421.       {
  422.     (void) fclose( st.file );
  423.     return( "bad node count in state file\n" );
  424.       }
  425.  
  426.     ClearInputs();
  427.  
  428.     if( analyzerON )
  429.     StopAnalyzer();
  430.  
  431.     sim_time0 = cur_delta = 0;
  432.  
  433.     st.errs = 0;
  434.     st.restore = restore;
  435.     walk_net( rd_stvalue, (char *) &st );
  436.  
  437.     NoInit();
  438.  
  439.     if( analyzerON )
  440.     RestartAnalyzer( sim_time0, cur_delta, FALSE );
  441.  
  442.     if( st.file == NULL )
  443.       {
  444.     (void) sprintf( fname, "premature EOF in state file (%d errors)\n",
  445.       st.errs );
  446.     return( fname );
  447.       }
  448.  
  449.     (void) fclose( st.file );
  450.  
  451.     if( st.errs != 0 )
  452.       {
  453.     (void) sprintf( fname, "%d errors found in state file\n", st.errs );
  454.     return( fname );
  455.       }
  456.     return( NULL );
  457.   }
  458.  
  459.  
  460. public int info( n, which )
  461.   register nptr  n;
  462.   char           *which;
  463.   {
  464.     register tptr  t;
  465.     register lptr  l;
  466.     char           *name;
  467.  
  468.     if( n == NULL )
  469.     return( 0 );
  470.  
  471.     if( int_received )
  472.     return( 1 );
  473.  
  474.     name = pnode( n );
  475.     while( n->nflags & ALIAS )
  476.     n = n->nlink;
  477.  
  478.     if( n->nflags & MERGED )
  479.       {
  480.     lprintf( stdout, "%s => node is inside a transistor stack\n", name );
  481.     return( 1 );
  482.       }
  483.  
  484.     pvalue( name, n );
  485.     if( n->nflags & INPUT )
  486.     lprintf( stdout, "[NOTE: node is an input] " );
  487.     lprintf( stdout, "(vl=%.2f vh=%.2f) ", n->vlow, n->vhigh );
  488.     if( n->nflags & USERDELAY )
  489.     lprintf( stdout, "(tplh=%d, tphl=%d) ", n->tplh, n->tphl );
  490.     lprintf( stdout, "(%4.3f pf) ", n->ncap );
  491.  
  492.     if( *which == '?' )
  493.       {
  494.     lprintf( stdout, "is computed from:\n" );
  495.     for( l = n->nterm; l != NULL and int_received == 0; l = l->next )
  496.       {
  497.         t = l->xtor;
  498.         lprintf( stdout, "  " );
  499.         if( debug == 0 )
  500.           {
  501.         char  *drive = NULL;
  502.         nptr  rail;
  503.  
  504.         rail = (t->drain->nflags & POWER_RAIL) ? t->drain : t->source;
  505.         if( BASETYPE( t->ttype ) == NCHAN and rail == GND_node )
  506.             drive = "pulled down by ";
  507.         else if( BASETYPE( t->ttype ) == PCHAN and rail == VDD_node )
  508.             drive = "pulled up by ";
  509.         else if( BASETYPE( t->ttype ) == DEP and rail == VDD_node and
  510.           other_node( t, rail ) == t->gate )
  511.             drive = "pullup ";
  512.         else
  513.             ptrans( t );
  514.  
  515.         if( drive != NULL )
  516.           {
  517.             lprintf( stdout, drive );
  518.             pgvalue( t );
  519.             pr_t_res( stdout, t->r );
  520.             if( t->tlink != t and (treport & REPORT_TCOORD) )
  521.             lprintf( stdout, " <%d,%d>\n", t->x.pos, t->y.pos );
  522.             else
  523.             lprintf( stdout, "\n" );
  524.           }
  525.           }
  526.         else
  527.         ptrans( t );
  528.       }
  529.       }
  530.     else
  531.       {
  532.     lprintf( stdout, "affects:\n" );
  533.     for( l = n->ngate; l != NULL and int_received == 0; l = l->next )
  534.         ptrans( l->xtor );
  535.       }
  536.  
  537.     if( int_received )
  538.     lprintf( stdout, "-- interrupted\n" );
  539.  
  540.     if( n->events != NULL )
  541.       {
  542.     register evptr  e;
  543.  
  544.     lprintf( stdout, "Pending events:\n" );
  545.     for( e = n->events; e != NULL; e = e->nlink )
  546.         lprintf( stdout, "   transition to %c at %2.1fns\n",
  547.           "0XX1"[e->eval], d2ns( e->ntime ) );
  548.       }
  549.  
  550.     return( 1 );
  551.   }
  552.